home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / appl / napsaterm / tek4010.c < prev    next >
C/C++ Source or Header  |  1994-05-14  |  45KB  |  1,232 lines

  1. /* Support for opening a tek4010 window from napsaterm on the Amiga.  This
  2.    option is enabled if the symbol TEKTRONICS is defined at compile time. */
  3.  
  4. /* tek4010.c is by RKNOP, Robert Knop, rknop@mop.caltech.edu */
  5.  
  6. /* tek4010 version 1.4 beta */
  7.  
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include "amiga.h"
  12. #include "nifty.h"
  13. #include "napsaprefs.h"
  14. #include "wimp.h"
  15. #include "nio.h"
  16. #include "ascii_ctrl.h"
  17. #include <graphics/displayinfo.h>
  18. #include <graphics/gfxmacros.h>
  19. #include <intuition/screens.h>
  20. #include <libraries/asl.h>
  21. #include <libraries/gadtools.h>
  22. #include <proto/asl.h>
  23. #include <proto/diskfont.h>
  24. #include <proto/intuition.h>
  25. #include <proto/gadtools.h>
  26. #include <proto/graphics.h>
  27. #include <proto/keymap.h>
  28. #include <proto/console.h>
  29. /*
  30. #include <proto/exec.h>
  31. */
  32.  
  33. #ifdef TEKTRONICS
  34. /*#echo "Compiling tek4010 unit"*/
  35.  
  36. /********** NOTE -- This is a hack I'm using to get bloody napsaterm to link 
  37.             with the debugger! *************/
  38.  
  39. const UBYTE _DevName[]="Rob's Hack";
  40.  
  41. /**************** End of NOTE ***************************************************/
  42.  
  43. /* Local functions not needed by the outside */
  44.  
  45. int opentekwin(void);
  46. void calctekwinsize(void);
  47. void newtekfont(void);
  48. int decode_integer(char);
  49. void Safe_Move(struct RastPort *,WORD,WORD);
  50. void Safe_Draw(struct RastPort *,WORD,WORD);
  51. void Safe_Rect(struct RastPort *,WORD,WORD);
  52. void scrtotek(void);
  53. void graph_clear(void);
  54. void setdrawmode(ULONG mode,WORD noerase);
  55. void redrawtek(void);
  56. void gin_mode_toggle(struct MenuItem *);
  57. void ginmouse(struct IntuiMessage *msg);
  58. void ginkeys(struct IntuiMessage *);
  59. void sendreport(WORD,WORD,char);
  60. void menu_close(void);
  61. void tekmenu(struct IntuiMessage *);
  62. void chk_active(struct MenuItem *);
  63. void chk_front(struct MenuItem *);
  64.  
  65. #define FULLWIDTH  4096
  66. #define FULLHEIGHT 3120
  67. #define BUFFERSIZE 65536
  68.  
  69. int tekmode=0;          /*Global variable, 1 if tek window is current window*/
  70. int bypassmode=0;
  71. static int fullcursor=0;
  72. static char eolstring[]="\015\0\0";    /*End of report string <CR>*/
  73. static mode=TEK_ALPHA;
  74. static int buffermode=0;
  75. #define DEF_ACTIVE CHECKED
  76. #define DEF_FRONT CHECKED
  77. static int activateonswitch=DEF_ACTIVE;
  78. static int forwardonswitch=DEF_FRONT;
  79.  
  80. extern struct KeyMap *default_map;     /* In keymap.c */
  81. extern struct KeyMap *used_map;        /* In keymap.c */
  82. extern struct IOStdReq consolereq;     /* In keymap.c */
  83. #define ConsoleDevice (consolereq.io_Device)
  84.  
  85. extern struct Window *w;     /*vt100 window in wimp.c*/
  86. struct Window *tekwindow=NULL;
  87. static WORD maxx,maxy,minx,miny;
  88. long tekwinmask=0;
  89. static int winw,winh;
  90. static int tekwidth=FULLWIDTH,tekheight=FULLHEIGHT,tekleft=0,tekbot=0;
  91. static Point Aspect;
  92. static char *tekbuffer=NULL;
  93. static char *startbuffer,*endbuffer;
  94. #define ENDCHECK  if (endbuffer<tekbuffer) endbuffer+=BUFFERSIZE;
  95. static char tektitle[80];
  96.  
  97. /* Text/Font information */
  98.  
  99. static struct TextAttr deftekattr={"topaz.font",8,0x00,0x00};
  100. static struct TextAttr tekattr;
  101. static struct TextFont *tekfont;
  102.  
  103. /*Tektronics drawing variables*/
  104.  
  105. static int last_mode;
  106. static int esc_mode=0;
  107. static int first_vector=1,incr_pen_down=0;
  108. static WORD increment=4;              /*Move in incr mode*/
  109. static WORD lastx,lasty;              /*Previous position in screen coords*/
  110. static WORD tekx,teky;                /*Prev. pos. in tek coords*/
  111. static UWORD lyok;                    /* Flag, is last y out of bounds*/
  112. static char HiY,Extra,LoY,HiX,LoX;    /*Tektronics position*/
  113. static char LoYorExtra=0;           /*temp storage for ambiguity*/
  114. static char LastTag;                  /*Tag bits of last vector byte*/
  115.  
  116. /*********************************************************************************/
  117. /* Open the tek4010 window on the napsaterm public screen                        */
  118. /*   By nature, it opens to the full size of the screen sans the title bar.      */
  119. /*********************************************************************************/
  120.  
  121. static struct NewMenu tekmenus[]=
  122.    {   {NM_TITLE, "TEK4010",         0, 0, 0, 0,},
  123.        { NM_ITEM, "To VT102",        "T", 0, 0, tek_vt100,},
  124.        { NM_ITEM, "To Tek",          "G", 0, 0, vt100_tek,},
  125.        { NM_ITEM, "Graph Clear",     "C", 0, 0, graph_clear,},
  126.        { NM_ITEM, "Redraw",          "R", 0, 0, redrawtek,},
  127.        { NM_ITEM, "Set Font...",     "F", 0, 0, newtekfont,},
  128.        { NM_ITEM, NM_BARLABEL,       0, 0, 0, 0,},
  129.        { NM_ITEM, "Close",           "Q", 0, 0, menu_close,},
  130.        {NM_TITLE, "Config",          0, 0, 0, 0,},
  131.        { NM_ITEM, "Activate Windows",0,MENUTOGGLE|CHECKIT|DEF_ACTIVE,0,chk_active,},
  132.        { NM_ITEM, "Front Windows",   0,MENUTOGGLE|CHECKIT|DEF_FRONT,0,chk_front,},
  133.        {NM_TITLE, "GIN Cursor",      0, 0, 0, 0,},
  134.        { NM_ITEM, "Cursor On",       0,MENUTOGGLE|CHECKIT,0,gin_mode_toggle,},
  135. #define CURSOR_MENUNUM 2
  136.        {  NM_END, NULL,              0, 0, 0, 0,},
  137.    };
  138. static APTR visinfo;
  139. static struct Menu *menuStrip;
  140.  
  141. int opentekwin(void)
  142. {  ULONG modeID;
  143.    struct DisplayInfo di;
  144.    struct Screen *s;
  145.    char *pubscname;
  146.    static int first=1;     /*Flag, first call to opentekwin*/
  147.  
  148.    if (!(tekbuffer=AllocMem(BUFFERSIZE,MEMF_PUBLIC))) return(0);
  149.    startbuffer=endbuffer=tekbuffer;
  150.  
  151.    pubscname=np.pubscname;
  152.    s=LockPubScreen(pubscname);   /*Try to lock the public screen*/
  153.    if (!s && pubscname) s=LockPubScreen(pubscname=NULL);  /*Try def. pub scr*/
  154.    if (!s)     /*Complete and utter failure*/
  155.    {  FreeMem(tekbuffer,65536);
  156.       return(0);
  157.    }
  158.  
  159.    modeID=GetVPModeID(&s->ViewPort);
  160.    if (!GetDisplayInfoData(NULL,(UBYTE *)&di,sizeof(di),DTAG_DISP,modeID))
  161.    {  FreeMem(tekbuffer,65536);
  162.       UnlockPubScreen(NULL,s);
  163.       return(0);
  164.    }
  165.    Aspect.x=di.Resolution.x;  Aspect.y=di.Resolution.y;
  166.  
  167.    sprintf(tektitle,"%s (TEK-4010)",np.title ? np.title : ProgName);
  168.    tekwindow=
  169.       OpenWindowTags(NULL, WA_PubScreen,s , WA_Left,0 , WA_Top,s->BarHeight ,
  170.                      WA_Width,s->Width , WA_Height,s->Height-s->BarHeight ,
  171.                      WA_MinWidth,70 , WA_MinHeight, 30 ,
  172.                      WA_MaxWidth,s->Width , WA_MaxHeight,s->Height ,
  173.                      WA_ScreenTitle,ProgName , WA_Title,tektitle ,
  174.                      WA_Flags,WFLG_SMART_REFRESH | WFLG_CLOSEGADGET |
  175.                               WFLG_DEPTHGADGET | WFLG_DRAGBAR |
  176.                               WFLG_NOCAREREFRESH | WFLG_ACTIVATE |
  177.                               WFLG_SIZEGADGET ,
  178.                      WA_IDCMP,IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | 
  179.                               IDCMP_MENUPICK | IDCMP_RAWKEY ,
  180.                      TAG_DONE);
  181.    UnlockPubScreen(NULL,s);
  182.  
  183.    if (!tekwindow) return(0);
  184.    visinfo=GetVisualInfo(s,TAG_END);      /*Check ret val?*/
  185.    menuStrip=CreateMenus(tekmenus,TAG_END);      /*Check return?*/
  186.    LayoutMenus(menuStrip,visinfo,TAG_END);       /*Check return?*/
  187.    SetMenuStrip(tekwindow,menuStrip);            /*Check return?*/
  188.  
  189.    tekwinmask=1<<tekwindow->UserPort->mp_SigBit;
  190.    calctekwinsize();
  191.    setdrawmode(JAM1,1);
  192.    if (first)
  193.    {  tekattr=deftekattr;        /*Set to default the first time only*/
  194.       first=0;
  195.    }
  196.    if (!(tekfont=OpenDiskFont(&tekattr)))
  197.    {  tekattr=deftekattr;       /*Failed to open font, open topaz 8*/
  198.       tekfont=OpenDiskFont(&tekattr);
  199.    }
  200.    SetFont(tekwindow->RPort,tekfont);      /*Set font for alpha mode*/
  201.    graph_clear();     /*Always start with cleared graphics screen*/
  202.    return(1);
  203. }
  204.  
  205. /******************************************************************************/
  206. /* closetekwin() -- close the tek window, quit tek terminal mode              */
  207. /******************************************************************************/
  208.  
  209. void closetekwin(void)
  210. {  struct Message *msg;
  211.  
  212.    if (!tekwindow) return;
  213.    tekmode=0;
  214.    tekwinmask=0;
  215.    while (msg=GetMsg(tekwindow->UserPort))     /*Clean messages out of user port*/
  216.       ReplyMsg(msg);
  217.    ClearMenuStrip(tekwindow);                  /*Get rid of those GadTools menus*/
  218.    FreeMenus(menuStrip);
  219.    FreeVisualInfo(visinfo);
  220.    CloseWindow(tekwindow);
  221.    tekwindow=NULL;                     /*Make sure we know there is no tekwindow*/
  222.    CloseFont(tekfont);                 /*Close the font, we no longer need it*/
  223.    FreeMem(tekbuffer,65536);
  224. }
  225.  
  226. /******************************************************************************/
  227. /* calctekwinsize() -- load winw and winh according to proper Tek screen size */
  228. /******************************************************************************/
  229.  
  230. void calctekwinsize(void)
  231. {  int w,h;
  232.  
  233.    minx=tekwindow->BorderLeft;
  234.    maxx=tekwindow->Width-tekwindow->BorderRight-1;
  235.    w=maxx-minx;
  236.    miny=tekwindow->BorderTop;
  237.    maxy=tekwindow->Height-tekwindow->BorderBottom-1;
  238.    h=maxy-miny;
  239.  
  240.    winh=h;
  241.    winw=(tekwidth*winh*Aspect.y) / (tekheight*Aspect.x);
  242.    if (winw>w)
  243.    {  winw=w;
  244.       winh=(tekheight*winw*Aspect.x) / (tekwidth*Aspect.y);
  245.    }
  246. }
  247.  
  248. /*****************************************************************************/
  249. /* Put up the ASL font requester to get a new font                           */
  250. /*****************************************************************************/
  251.  
  252. void newtekfont(void)
  253. {  struct FontRequester *req;
  254.    struct TextAttr oldattr;
  255.  
  256.    if (!tekwindow) return;
  257.    if (!(req=(struct FontRequester *)AllocAslRequestTags(
  258.               ASL_FontRequest,ASL_FontName,(ULONG)tekattr.ta_Name,
  259.               ASL_FontHeight,(ULONG)tekattr.ta_YSize,
  260.               ASL_FuncFlags,FONF_FIXEDWIDTH,ASL_Window,tekwindow,TAG_END)))
  261.       return;
  262.    if (AslRequest(req,NULL))
  263.    {  oldattr=tekattr;
  264.       tekattr=req->fo_Attr;
  265.       CloseFont(tekfont);       /*Close the old font*/
  266.       if (!(tekfont=OpenDiskFont(&tekattr)))       /*Try to open new font*/
  267.       {  tekattr=oldattr;
  268.          if (!(tekfont=OpenDiskFont(&tekattr)))      /*If fail, go back to old*/
  269.          {  tekattr=deftekattr;
  270.             tekfont=OpenDiskFont(&tekattr);  /*If _that_ fails, go to topaz/8*/
  271.          }
  272.       }
  273.       SetFont(tekwindow->RPort,tekfont);
  274.    }
  275.    FreeAslRequest(req);
  276. }
  277. /*****************************************************************************/
  278. /* Set tektronics mode                                                       */
  279. /*****************************************************************************/
  280.  
  281. void set_tekmode(unsigned short newmode)
  282. {  struct RastPort *rp;
  283.    WORD x,y;
  284.  
  285.    rp=tekwindow->RPort;
  286.    if ((mode=newmode)==TEK_ALPHA)     /*Do some bounds checking*/
  287.    {  if (!(rp->cp_x > (x=tekwindow->Width - tekwindow->BorderRight - 
  288.                           tekfont->tf_XSize)))
  289.          x=rp->cp_x;
  290.       if (!(rp->cp_y < (y=tekwindow->BorderTop + tekfont->tf_Baseline)))
  291.          y=rp->cp_y;
  292.       Move(rp,x,y);    /*Now we know it is safe to render a letter*/
  293.    }
  294. }
  295.  
  296. /****************************************************************************/
  297. /*  Switch from vt100 mode to tek mode without clearing the tek screen      */
  298. /****************************************************************************/
  299.  
  300. void vt100_tek(void)
  301. {
  302.    if (!tekwindow)
  303.    {  if (!opentekwin()) return;
  304.    }
  305.    if (activateonswitch) ActivateWindow(tekwindow);
  306.    if (forwardonswitch) WindowToFront(tekwindow);
  307.    tekmode=1;
  308. }
  309.  
  310. /*******************************************************************************/
  311. /*  Switch from tek mode to vt100 mode                                         */
  312. /*******************************************************************************/
  313.  
  314. void tek_vt100(void)
  315. {
  316.    if (activateonswitch) ActivateWindow(w);
  317.    if (forwardonswitch) WindowToFront(w);
  318.    tekmode=0;
  319. }
  320.  
  321. /******************************************************************************/
  322. /* graph_clear() -- clear the graphics screen and the tek buffer              */
  323. /******************************************************************************/
  324.  
  325. void graph_clear(void)
  326. {  WORD xscr,yscr;
  327.  
  328.    startbuffer=endbuffer=tekbuffer;
  329.    SetAPen(tekwindow->RPort,0);
  330.    RectFill(tekwindow->RPort,tekwindow->BorderLeft,tekwindow->BorderTop,
  331.             tekwindow->Width-1-tekwindow->BorderRight,
  332.             tekwindow->Height-1-tekwindow->BorderBottom);
  333.    HiY=Extra=LoY=HiX=LoX=LoYorExtra=(char)0;   /*Initialize tek position variables*/
  334.    first_vector=1;               /*Always start out with first vector*/
  335.    esc_mode=0;                   /*Always clear escape mode*/
  336.    SetDrPt(tekwindow->RPort,0xffff);       /*Start with solid draw pattern*/
  337.    setdrawmode(JAM1,1);
  338.    esc_mode=0;      /*Start with esc_mode cleared*/
  339.    set_tekmode(TEK_ALPHA);          /*Start in alpha mode -oo-*/
  340.    bypassmode=0;    /*Start with bypass mode off*/
  341.    xscr=tekwindow->BorderLeft;
  342.    yscr=tekwindow->BorderTop+tekfont->tf_Baseline+1;
  343.    Safe_Move(tekwindow->RPort,xscr,yscr);                       /*Home*/
  344.    scrtotek();
  345. }
  346.  
  347. /*****************************************************************************/
  348. /* setdrawmode() -- changes drawing mode for screen                          */
  349. /*****************************************************************************/
  350.  
  351. void setdrawmode(ULONG mode,WORD noerase)
  352. {  struct DrawInfo *di;
  353.  
  354.    if (di=GetScreenDrawInfo(tekwindow->WScreen))
  355.    {  if (noerase) SetAPen(tekwindow->RPort,di->dri_Pens[TEXTPEN]);
  356.       else SetAPen(tekwindow->RPort,di->dri_Pens[BACKGROUNDPEN]);
  357.       FreeScreenDrawInfo(tekwindow->WScreen,di);
  358.    }
  359.    else
  360.    {  if (noerase) SetAPen(tekwindow->RPort,1);
  361.       else SetAPen(tekwindow->RPort,0);
  362.    }
  363.    SetDrMd(tekwindow->RPort,mode);
  364. }
  365.  
  366. /*****************************************************************************/
  367. /* gin_mode_toggle() -- turn on/off GIN cursor                               */
  368. /*****************************************************************************/
  369.  
  370.     /**** NOTE : deal with setting the checkmark in the menu!!!! *****/
  371.     /**** Also deal with setting the pointer to crosshairs ****/
  372.  
  373. UWORD __chip Crosshairs[] =     /*Done by hand*/
  374. {  0x0000,0x0000,   /* Two system reserved words */
  375.  
  376.    0x0000,0x0000,
  377.    0x0000,0x0100,
  378.    0x7efc,0x0100,
  379.    0x4004,0x0100,
  380.    0x4004,0x0100,
  381.    0x4004,0x0100,
  382.    0x4004,0x0100,
  383.    0x4004,0x0100,
  384.    0x0100,0xfffe,
  385.    0x4004,0x0100,
  386.    0x4004,0x0100,
  387.    0x4004,0x0100,
  388.    0x4004,0x0100,
  389.    0x4004,0x0100,
  390.    0x7efc,0x0100,
  391.    0x0000,0x0100,
  392.  
  393.    0x0000,0x0000           /* Two more system reserved words */
  394. };
  395.  
  396. void gin_mode_toggle(struct MenuItem *menu)
  397. {  static int lasttekmode=TEK_ALPHA,lastbuffermode;
  398.    struct MenuItem *item;
  399.  
  400.    if (menu) item=menu;
  401.    else item=ItemAddress(menuStrip,CURSOR_MENUNUM);
  402.    if ( (menu && (item->Flags&CHECKED)) || ((!menu) && (mode!=TEK_GIN)) )
  403.    {  lasttekmode=mode;
  404.       lastbuffermode=buffermode;
  405.       buffermode=0;
  406.       set_tekmode(TEK_GIN);
  407.       bypassmode=1;
  408.       if (fullcursor)
  409.          ModifyIDCMP(tekwindow,tekwindow->IDCMPFlags |
  410.                                IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS);
  411.       else ModifyIDCMP(tekwindow,tekwindow->IDCMPFlags|IDCMP_MOUSEBUTTONS);
  412.       SetPointer(tekwindow,Crosshairs,16,16,-8,-8);
  413.       item->Flags|=CHECKED;
  414.       ResetMenuStrip(tekwindow,menuStrip);
  415.    }
  416.    else
  417.    {  set_tekmode(lasttekmode);
  418.       /*set_tekmode(TEK_ALPHA);*/
  419.       lasttekmode=TEK_ALPHA;
  420.       buffermode=lastbuffermode;
  421.       bypassmode=0;
  422.       ModifyIDCMP(tekwindow,tekwindow->IDCMPFlags & 
  423.                             ~(IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS));
  424.       ClearPointer(tekwindow);
  425.       item->Flags &= ~CHECKED;
  426.       ResetMenuStrip(tekwindow,menuStrip);
  427.    }
  428. }
  429.  
  430. /*****************************************************************************/
  431. /* ginmouse() -- deal with GIN mouse events                                  */
  432. /*****************************************************************************/
  433.  
  434. void ginmouse(struct IntuiMessage *msg)
  435. {  WORD xscr,yscr,xgin,ygin;
  436.  
  437.    if (msg->Class==MOUSEMOVE)
  438.    {  /* Deal with moving big crosshairs if necessary */
  439.    }
  440.    else if (msg->Class==MOUSEBUTTONS)
  441.    {  if (msg->Code==SELECTDOWN)
  442.       {  Forbid();
  443.          xscr=tekwindow->MouseX;
  444.          yscr=tekwindow->MouseY;
  445.          Permit();
  446.          xgin=((xscr-tekwindow->BorderLeft)*tekwidth)/winw;
  447.          ygin=(-(yscr-tekwindow->BorderTop-winh)*tekheight)/winh;
  448.          sendreport(xgin,ygin,' ');
  449.          gin_mode_toggle(NULL);  /*quit GIN mode*/
  450.       }
  451.    }
  452.    ReplyMsg((struct Message *)msg);
  453. }
  454.  
  455. /*****************************************************************************/
  456. /* ginkeys() -- deal with GIN RAWKEY events                                  */
  457. /*****************************************************************************/
  458.  
  459. void ginkeys(struct IntuiMessage *msg)
  460. {  struct InputEvent ie;
  461.    char buf[4];
  462.    WORD xscr,yscr,xgin,ygin;
  463.  
  464.    if (msg->Code & IECODE_UP_PREFIX) return;
  465.    ie.ie_Code=msg->Code;
  466.    ie.ie_NextEvent=NULL;
  467.    ie.ie_SubClass=0;
  468.    ie.ie_Class=IECLASS_RAWKEY;
  469.    ie.ie_Qualifier=msg->Qualifier;
  470.    ie.ie_position.ie_addr=*((APTR *)msg->IAddress);
  471.    RawKeyConvert(&ie,buf,4,np.national ? used_map : default_map);
  472.  
  473.    /*** Send report with mouse x,y tek position */
  474.    Forbid();
  475.    xscr=tekwindow->MouseX;
  476.    yscr=tekwindow->MouseY;
  477.    Permit();
  478.    xgin=((xscr-tekwindow->BorderLeft)*tekwidth)/winw;
  479.    ygin=(-(yscr-tekwindow->BorderTop-winh)*tekheight)/winh;
  480.    sendreport(xgin,ygin,buf[0]);
  481.    ReplyMsg((struct Message *)msg);
  482.    gin_mode_toggle(NULL);
  483. }
  484.  
  485. /*****************************************************************************/
  486. /* sendreport() -- Send 4010 style report to host                            */
  487. /*   Pass x,y in 4014 4096-pixel coordinate system.                          */
  488. /*   This routine converts it to 1024 before sending the report              */
  489. /*****************************************************************************/
  490.  
  491. void sendreport(WORD x,WORD y,char c)
  492. {  char report[10];
  493.    int i=-1,j;
  494.  
  495.    if (c) report[++i]=c;
  496.    switch (mode)                  /* Set bits 2-3 of status based on mode*/
  497.    {  case TEK_POINT  : report[++i]=0x01; break;   /* Bit 0 always set */
  498.       case TEK_ALPHA  : report[++i]=0x05; break;
  499.       case TEK_VECTOR : report[++i]=0x09; break;
  500.       case TEK_GIN    : break;
  501.       default         : report[++i]=0x0d; break;
  502.    }
  503.    report[++i]=0x20 | ( (x & 0x0f80)>>7 );      /*HiX*/
  504.    report[++i]=0x20 | ( (x & 0x007c)>>2 );      /*LoX*/
  505.    report[++i]=0x20 | ( (y & 0x0f80)>>7 );      /*HiY*/
  506.    report[++i]=0x20 | ( (y & 0x007c)>>2 );      /*LoY*/
  507.    for (j=0;j<strlen(eolstring);j++)
  508.       report[++i]=eolstring[j];
  509.    report[++i]='\0';
  510.    nwrite(report,i);
  511. }
  512.  
  513. /*****************************************************************************/
  514. /* redrawtek() -- redraw tek window from buffer                              */
  515. /*****************************************************************************/
  516.  
  517. void redrawtek(void)
  518. {  char *c;
  519.  
  520.    /* Start with a simulation of graph_clear, all but the buffer clearing*/
  521.    SetAPen(tekwindow->RPort,0);
  522.    RectFill(tekwindow->RPort,tekwindow->BorderLeft,tekwindow->BorderTop,
  523.             tekwindow->Width-1-tekwindow->BorderRight,
  524.             tekwindow->Height-1-tekwindow->BorderBottom);
  525.    HiY=Extra=LoY=HiX=LoX=LoYorExtra=(char)0;    /*Initialize tek position variables*/
  526.    first_vector=1;               /*Always start out with first vector*/
  527.    esc_mode=0;                   /*Always clear escape mode*/
  528.    SetDrPt(tekwindow->RPort,0xffff);       /*Start with solid draw pattern*/
  529.    setdrawmode(JAM1,1);
  530.  
  531.    buffermode=1;
  532.    if (startbuffer>endbuffer)
  533.    {  c=tekout(startbuffer,tekbuffer+BUFFERSIZE);
  534.       c=tekout(tekbuffer,endbuffer);
  535.    }
  536.    else c=tekout(startbuffer,endbuffer);
  537.    buffermode=0;
  538.    /* Deal with c not being equal to text+count*/
  539. }
  540.  
  541. /********************************************************************************/
  542. /* tekout() -- handle characters incoming into the Tek screen                   */
  543. /*   Generally, this will be called from termout (see emulate.c).  It returns   */
  544. /*    a pointer to the first charcter after a return to VT100 mode, or to       */
  545. /*    endtext.  This way, termout can call tekout and use it's return value for */
  546. /*    updating its pointer into the string of characters which have been handled*/
  547. /********************************************************************************/
  548.  
  549. /***** Meanings of esc modes:
  550.    0      no escape
  551.    1      ESC
  552.    2      ESC [ or CSI
  553.    3      ESC "
  554.    4      ESC [ ?
  555.    6      ESC %
  556.    7      ESC % !
  557. ****/
  558.  
  559. char *tekout(char *text,char *endtext)
  560. {  char *c;
  561.    WORD xscr,yscr,xgin,ygin;
  562.    static int esc_number=0,seq_length=0;
  563.  
  564.    for (c=text;c<endtext;c++)
  565.    {  if (!buffermode)
  566.       {  *endbuffer=*c;
  567.          if (endbuffer-tekbuffer==BUFFERSIZE-1) endbuffer=tekbuffer;
  568.          else endbuffer++;
  569.          if (startbuffer>=endbuffer)
  570.          {  startbuffer++;
  571.             if  (startbuffer-tekbuffer==BUFFERSIZE-1) startbuffer=tekbuffer;
  572.          }
  573.       }
  574.  
  575.       if (mode==TEK_GIN)                   /* GIN (bypass) mode sequences */
  576.       {  switch(*c)
  577.          {  case ESC : if (esc_mode) {}
  578.                        else
  579.                        {  esc_mode=1;
  580.                           esc_number=0;
  581.                        }
  582.                        break;
  583.  
  584.             case ENQ : if (esc_mode==1)
  585.                        {  Forbid();
  586.                           xscr=tekwindow->MouseX;
  587.                           yscr=tekwindow->MouseY;
  588.                           Permit();
  589.                           xgin=((xscr-tekwindow->BorderLeft)*tekwidth)/winw;
  590.                           ygin=(-(yscr-tekwindow->BorderTop-winh)*tekheight)/winh;
  591.                           sendreport(xgin,ygin,'\0');
  592.                           gin_mode_toggle(NULL);  /*quit GIN mode*/
  593.                        }
  594.                        break;
  595.  
  596.             case LF  :
  597.             case CR  : gin_mode_toggle(NULL);     /*quit GIN mode, don't*/
  598.                        break;                     /* change esc_mode */
  599.  
  600.             case BS :
  601.             case VT :
  602.             case HT : if (esc_mode==0) gin_mode_toggle(NULL);
  603.                       else esc_mode=0;
  604.                       break;
  605.  
  606.             case BEL : DisplayBeep(tekwindow->WScreen);
  607.                        esc_mode=0;
  608.                        gin_mode_toggle(NULL);
  609.                        break;
  610.  
  611.             case CAN :
  612.             case SUB : esc_mode=0;   /* -oo- These just set bypass or GIN */
  613.                        break;
  614.  
  615.             case US : esc_mode=0;
  616.                       gin_mode_toggle(NULL);
  617.                       set_tekmode(TEK_ALPHA);
  618.                       break;
  619.  
  620.             case FF : if (esc_mode==1)
  621.                       {  gin_mode_toggle(NULL);
  622.                          graph_clear();
  623.                       }
  624.                       break;
  625.          }
  626.       }    /*End of GIN mode handling */
  627.  
  628.       else if (!esc_mode && (*c>=0x20))   /*If not a CTRL char or ESC sequence...*/
  629.       {  if ((mode==TEK_VECTOR)||(mode==TEK_POINT)||(mode==TEK_BLOCK))
  630.          {  if (decode_integer(*c))       /*Non-zero result indicates LoX rec.*/
  631.             {  tekx=((short)(HiX & 0x1f)<<7) |    /*Build new X tek position*/
  632.                     ((short)(LoX & 0x1f)<<2) |
  633.                     ((short)(Extra & 0x03));
  634.                teky=((short)(HiY & 0x1f)<<7) |    /*Build new Y tek position*/
  635.                     ((short)(LoY & 0x1f)<<2) |
  636.                     ((short)(Extra & 0x0c)>>2);
  637.                xscr=tekwindow->BorderLeft+(tekx*winw)/tekwidth;  /*Screen position*/
  638.                yscr=tekwindow->BorderTop+winh-(teky*winh)/tekheight;
  639.                if (mode==TEK_POINT)
  640.                {  WritePixel(tekwindow->RPort,xscr,yscr);  /*Does check bounds*/
  641.                   Safe_Move(tekwindow->RPort,xscr,yscr);
  642.                }
  643.                else
  644.                {  if (first_vector)
  645.                   {  Safe_Move(tekwindow->RPort,xscr,yscr);
  646.                      first_vector=0;
  647.                   }
  648.                   else
  649.                   {  if (mode==TEK_VECTOR)
  650.                         Safe_Draw(tekwindow->RPort,xscr,yscr);
  651.                      else
  652.                         Safe_Rect(tekwindow->RPort,xscr,yscr);
  653.                   }
  654.                }
  655.             }
  656.          }                 /*End of TEK_VECTOR and TEK_POINT handling*/
  657.          else if (mode==TEK_ALPHA)
  658.          {  if (tekwindow->RPort->cp_x >
  659.                    tekwindow->Width-tekwindow->BorderRight-tekfont->tf_XSize)
  660.             {  xscr=tekwindow->BorderLeft;
  661.                yscr=tekwindow->RPort->cp_y+tekfont->tf_YSize+1;
  662.                if ( (yscr+tekfont->tf_YSize-tekfont->tf_Baseline) > 
  663.                                           tekwindow->Height-tekwindow->BorderBottom )
  664.                   yscr=tekwindow->BorderTop+tekfont->tf_Baseline+1;
  665.                Safe_Move(tekwindow->RPort,xscr,yscr);
  666.             }
  667.             Text(tekwindow->RPort,c,1);  /*Write the character*/            
  668.          }                 /*End of TEK_ALPHA handling*/
  669.          else if (mode==TEK_INCR)
  670.          {  if (*c==' ') incr_pen_down=0;
  671.             else if (*c=='P') incr_pen_down=1;
  672.             else
  673.             {  switch(*c)
  674.                {  case 'D' : teky+=1; break;
  675.                   case 'E' : teky+=1; tekx+=1; break;
  676.                   case 'A' : tekx+=1; break;
  677.                   case 'I' : teky-=1; tekx+=1; break;
  678.                   case 'H' : teky-=1;
  679.                   case 'J' : teky-=1; tekx-=1; break;
  680.                   case 'B' : tekx-=1;
  681.                   case 'F' : tekx-=1; teky+=1; break;
  682.                }
  683.                xscr=tekwindow->BorderLeft+(tekx*winw)/tekwidth;  /*Screen position*/
  684.                yscr=tekwindow->BorderTop+winh-(teky*winh)/tekheight;
  685.                Safe_Draw(tekwindow->RPort,xscr,yscr);
  686.             }
  687.          }
  688.       }
  689.  
  690.  
  691.       /* NOTE -- ESC sequences will be interpreted in all modes, even if they
  692.          aren't supposed to be.   Fix this later?*/
  693.       /* GIN mode is a special case, above */
  694.  
  695.       else                        /*Handling of ESC sequences and CTRL codes*/
  696.       {  ++seq_length;
  697.          if ((esc_mode==3 || esc_mode==4) && *c>='0' && *c<='9')
  698.             esc_number=10*esc_number+ *c-'0';
  699.          else switch(*c)             /* *c is a control character of some sort*/
  700.          {  /* Vector & Point mode sequences */
  701.             case ESC : if (esc_mode) {}      /* ESC ESC == ESC */
  702.                        else
  703.                        {  esc_mode=seq_length=1;
  704.                           esc_number=0;
  705.                        }
  706.                        break;
  707.  
  708.             case STX : if (esc_mode==1 && mode==TEK_VECTOR)
  709.                        {  set_tekmode(TEK_BLOCK);
  710.                           first_vector=1;
  711.                        }
  712.                        esc_mode=0;
  713.                        break;     
  714.  
  715.             case ETX : if (esc_mode==1 && mode==TEK_BLOCK)
  716.                        {  set_tekmode(TEK_VECTOR);
  717.                           first_vector=1;
  718.                        }
  719.                        esc_mode=0;
  720.                        break;
  721.  
  722.             case SOH : if (esc_mode==1) setdrawmode(JAM1,1);
  723.                        esc_mode=0;              /*Writing mode = draw*/
  724.                        break;
  725.  
  726.             case DLE : if (esc_mode==1) setdrawmode(JAM1,0);
  727.                        esc_mode=0;              /*Writing mode = erase*/
  728.                        break;
  729.  
  730.             case NAK : if (esc_mode==1) setdrawmode(INVERSVID,1);
  731.                        esc_mode=0;              /*Writing mode=invert*/
  732.                        break;
  733.  
  734.             case EM :  if (esc_mode==1) setdrawmode(JAM2,1);
  735.                        esc_mode=0;              /*Writing mode=replace*/
  736.                        break;
  737.  
  738.             case BEL : DisplayBeep(tekwindow->WScreen);
  739.                        esc_mode=0;
  740.                        break;
  741.       
  742.             case CR  : if (mode!=TEK_ALPHA) mode=TEK_ALPHA;
  743.                        else
  744.                        {  Safe_Move(tekwindow->RPort,tekwindow->BorderLeft,
  745.                                     tekwindow->RPort->cp_y);
  746.                           scrtotek();
  747.                        }
  748.                        break;
  749.       
  750.             case FF : if (esc_mode==1)
  751.                       {  graph_clear();   /*More??*/
  752.                          if (mode==TEK_INCR) set_tekmode(TEK_ALPHA);
  753.                       }
  754.                       esc_mode=0;
  755.                       break;
  756.       
  757.             case CAN : if (esc_mode==0)
  758.                        {  tek_vt100();          /*Switch back to vt100 mode*/
  759.                           if (!buffermode)
  760.                           {   endbuffer--;  /*Kill vt100 esc seq from buffer*/
  761.                               ENDCHECK;
  762.                           }
  763.                           return(++c);          /*Return position to keep going*/
  764.                        }
  765.                        else if (esc_mode==1)
  766.                        {  /*set bypass condition -oo- !!!!!!!!!*/
  767.                           esc_mode=0;
  768.                           if (mode==TEK_ALPHA) graph_clear();
  769.                        }
  770.                        else esc_mode=0;
  771.                        break;
  772.       
  773.       
  774.             case SUB : if (esc_mode==1)
  775.                        {  gin_mode_toggle(NULL);
  776.                           if (!buffermode)
  777.                           {  endbuffer-=seq_length;  /*No buffering GIN mode*/
  778.                              ENDCHECK;
  779.                           }
  780.                           esc_mode=esc_number=0;
  781.                        }
  782.                        else esc_mode=0;
  783.                        break;
  784.       
  785.             case FS  : set_tekmode(TEK_POINT);
  786.                        esc_mode=0;
  787.                        break;
  788.       
  789.             case GS  : set_tekmode(TEK_VECTOR);
  790.                        esc_mode=0;
  791.                        first_vector=1;
  792.                        break;
  793.       
  794.             case RS  : set_tekmode(TEK_INCR);
  795.                        esc_mode=0;
  796.                        break;
  797.       
  798.             case US  : set_tekmode(TEK_ALPHA);
  799.                        esc_mode=0;
  800.                        break;
  801.       
  802.             case '`' : if (esc_mode==1)
  803.                        {  SetDrPt(tekwindow->RPort,0xffff);
  804.                           SetAPen(tekwindow->RPort,1);
  805.                           esc_mode=0;
  806.                        }
  807.                        break;
  808.       
  809.             case 'a' : if (esc_mode==1)
  810.                        {  SetDrPt(tekwindow->RPort,0xaaaa);
  811.                           SetAPen(tekwindow->RPort,1);
  812.                        }
  813.                        esc_mode=0;
  814.                        break;
  815.       
  816.             case 'b' : if (esc_mode==1)
  817.                        {  SetDrPt(tekwindow->RPort,0xfafa);
  818.                           SetAPen(tekwindow->RPort,1);
  819.                        }
  820.                        esc_mode=0;
  821.                        break;
  822.       
  823.             case 'c' : if (esc_mode==1)
  824.                        {  SetDrPt(tekwindow->RPort,0xeeee);
  825.                           SetAPen(tekwindow->RPort,1);
  826.                        }
  827.                        esc_mode=0;
  828.                        break;
  829.       
  830.             case 'd' : if (esc_mode==1)
  831.                        {  SetDrPt(tekwindow->RPort,0xfcfc);
  832.                           SetAPen(tekwindow->RPort,1);
  833.                        }
  834.                        esc_mode=0;
  835.                        break;
  836.       
  837.             case 'e' : if (esc_mode==1)
  838.                        {  SetDrPt(tekwindow->RPort,0xff55);
  839.                           SetAPen(tekwindow->RPort,1);
  840.                        }
  841.                        esc_mode=0;
  842.                        break;
  843.       
  844.             case 'f' : if (esc_mode==1)
  845.                        {  SetDrPt(tekwindow->RPort,0xff6c);
  846.                           SetAPen(tekwindow->RPort,1);
  847.                        }
  848.                        esc_mode=0;
  849.                        break;
  850.       
  851.             case 'g' : if (esc_mode==1)
  852.                        {  SetDrPt(tekwindow->RPort,0xf0f0);
  853.                           SetAPen(tekwindow->RPort,1);
  854.                        }
  855.                        else if (esc_mode==3)   /*From SuperMode*/
  856.                        {  tek_vt100();
  857.                           if (!buffermode)
  858.                           {  endbuffer-=seq_length; /*Remove to vt100 seq from buf*/
  859.                              ENDCHECK;
  860.                           }
  861.                           esc_mode=0;
  862.                           return(++c);
  863.                        }
  864.                        /* Note -- I ought to check to make sure there was a 0*/
  865.                        esc_mode=0;
  866.                        break;
  867.       
  868.             case 'h' : if (esc_mode==1)
  869.                        {  SetDrPt(tekwindow->RPort,0xffff);
  870.                           SetAPen(tekwindow->RPort,2);
  871.                        }
  872.                        else if (esc_mode==4)     /*ESC [ ? <number> h*/
  873.                        {  if (esc_number==38) {}  /*Switch to tek-- do nil*/
  874.                        }
  875.                        esc_mode=0;
  876.                        break;
  877.       
  878.             case 'i' : if (esc_mode==1)
  879.                        {  SetDrPt(tekwindow->RPort,0xaaaa);
  880.                           SetAPen(tekwindow->RPort,2);
  881.                        }
  882.                        esc_mode=0;
  883.                        break;
  884.       
  885.             case 'j' : if (esc_mode==1)
  886.                        {  SetDrPt(tekwindow->RPort,0xfafa);
  887.                           SetAPen(tekwindow->RPort,2);
  888.                        }
  889.                        esc_mode=0;
  890.                        break;
  891.       
  892.             case 'k' : if (esc_mode==1)
  893.                        {  SetDrPt(tekwindow->RPort,0xeeee);
  894.                           SetAPen(tekwindow->RPort,2);
  895.                        }
  896.                        esc_mode=0;
  897.                        break;
  898.       
  899.             case 'l' : if (esc_mode==1)
  900.                        {  SetDrPt(tekwindow->RPort,0xfcfc);
  901.                           SetAPen(tekwindow->RPort,2);
  902.                        }
  903.                        else if (esc_mode==4)     /*ESC [ ? <number> l*/
  904.                        {  if (esc_number==38)   /*Switch to vt100*/
  905.                           {  esc_mode=0;
  906.                              tek_vt100();
  907.                              if (!buffermode)
  908.                              {  endbuffer-=seq_length; /*Remove esc seq from buffer*/
  909.                                 ENDCHECK;
  910.                              }
  911.                              return(++c);
  912.                           }
  913.                        }
  914.                        esc_mode=0;
  915.                        break;
  916.       
  917.             case 'm' : if (esc_mode==1)
  918.                        {  SetDrPt(tekwindow->RPort,0xff55);
  919.                           SetAPen(tekwindow->RPort,2);
  920.                        }
  921.                        esc_mode=0;
  922.                        break;
  923.       
  924.             case 'n' : if (esc_mode==1)
  925.                        {  SetDrPt(tekwindow->RPort,0xff6c);
  926.                           SetAPen(tekwindow->RPort,2);
  927.                        }
  928.                        esc_mode=0;
  929.                        break;
  930.       
  931.             case 'o' : if (esc_mode==1)
  932.                        {  SetDrPt(tekwindow->RPort,0xf0f0);
  933.                           SetAPen(tekwindow->RPort,2);
  934.                        }
  935.                        esc_mode=0;
  936.                        break;
  937.       
  938.             case '?' : if (esc_mode==1)
  939.                        {  LoY=0x7f;  /*DEL character replacement*/
  940.                           esc_mode=0;
  941.                        }
  942.                        else if (esc_mode==2)     /*<CSI>*/
  943.                           esc_mode=4;
  944.                        else esc_mode=0;
  945.                        break;
  946.       
  947.             /* End of Vector Mode sequences*/
  948.             /* Alpha mode sequences */
  949.             /* See Vector mode for ESC,BEL,ESC/FF,ESC/SUB,FS,GS,RS,CR*/
  950.       
  951.             case ENQ : /* -oo- report terminal status */
  952.                        if (esc_mode) esc_mode=0;
  953.                        break;
  954.       
  955.             case DEL:  if (esc_mode) break;
  956.                        /* Otherwise same as BS */
  957.             case BS  : /* Move one space left */
  958.                        if (esc_mode) esc_mode=0;
  959.                        if (mode==TEK_ALPHA)
  960.                        {  if (tekwindow->RPort->cp_x < tekfont->tf_XSize)
  961.                              xscr=tekwindow->BorderLeft;
  962.                           else xscr=tekwindow->RPort->cp_x-tekfont->tf_XSize;
  963.                           Safe_Move(tekwindow->RPort,xscr,tekwindow->RPort->cp_y);
  964.                           scrtotek();
  965.                        }
  966.                        break;
  967.       
  968.             case HT  : /*Horiz tab*/
  969.                        if (esc_mode) esc_mode=0;
  970.                        break;
  971.       
  972.             case LF  : /*CRLF*/
  973.                        if ( esc_mode==0 && mode==TEK_ALPHA )
  974.                        {  xscr=tekwindow->BorderLeft;
  975.                           yscr=tekwindow->RPort->cp_y+tekfont->tf_YSize+1;
  976.                           if ( (yscr+tekfont->tf_YSize-tekfont->tf_Baseline) > 
  977.                                      tekwindow->Height-tekwindow->BorderBottom )
  978.                              yscr=tekwindow->BorderTop+tekfont->tf_Baseline+1;
  979.                           Safe_Move(tekwindow->RPort,xscr,yscr);
  980.                           scrtotek();
  981.                        }
  982.                        /* esc_mode=0; */ /* ESC LF == ESC */
  983.                        break;
  984.       
  985.             case VT  : /*Move one line up*/
  986.                        if (esc_mode) esc_mode=0;
  987.                        break;
  988.       
  989.             /* End of Alpha mode sequences*/
  990.             /* Incremental Plot Mode sequences*/
  991.             /* End of Incremental Plot Mode sequences*/
  992.             /* SuperMode sequences -- this needs some work!*/
  993.       
  994.             case '"' : if (esc_mode==1) esc_mode=3;
  995.                        else esc_mode=0;
  996.                        break;
  997.       
  998.             case '[' : if (esc_mode==1) esc_mode=2;  /*<CSI>*/
  999.                        else esc_mode=0;
  1000.                        break;
  1001.  
  1002.             case '%' : if (esc_mode==1) esc_mode=6;
  1003.                        else esc_mode=0;
  1004.                        break;
  1005.  
  1006.             case '!' : if (esc_mode==6) esc_mode=7;
  1007.                        else esc_mode=0;
  1008.                        break;
  1009.  
  1010.             case '0' : if (esc_mode==7) vt100_tek();
  1011.                        esc_mode=0;
  1012.                        break;
  1013.  
  1014.             case '1' : if (esc_mode==7)
  1015.                        {  tek_vt100();
  1016.                           if (!buffermode)
  1017.                           {  endbuffer-=seq_length;  /*Remove esc seq from buffer*/
  1018.                              ENDCHECK;
  1019.                           }
  1020.                        }
  1021.                        esc_mode=0;
  1022.                        break;
  1023.  
  1024.             case '2' : if (esc_mode==1)
  1025.                        {  tek_vt100();
  1026.                           if (!buffermode)
  1027.                           {  endbuffer-=seq_length;
  1028.                              ENDCHECK;
  1029.                           }
  1030.                        }
  1031.                        esc_mode=0;
  1032.                        break;
  1033.  
  1034.             /* case g h l ?  handled above */
  1035.       
  1036.             /* End of SuperMode sequences */
  1037.       
  1038.             default : if (esc_mode) esc_mode=0;
  1039.                       break;
  1040.          }        /*End of switch over escaped characters*/
  1041.       }
  1042.    }            /*End of the massive for loop over input characters*/
  1043.    return(c);        /*Should be text+count*/
  1044. }
  1045.  
  1046. /**********************************************************************/
  1047. /* decode_integer()          Works on decoding a Tek integer          */
  1048. /*    Returns 1 if LoX was received, and terminal should act on the   */
  1049. /*      integer that has just been built.                             */
  1050. /**********************************************************************/
  1051.  
  1052. int decode_integer(char c)
  1053. {  char tagbits;
  1054.    int rv;
  1055.  
  1056.    rv=0;
  1057.    tagbits=c & 0x60;
  1058.    if (tagbits==0x20)        /*HiY or HiX*/
  1059.    {  if (LastTag==0x60)       /*Last was LoY, this is HiX*/
  1060.       {  HiX=c;
  1061.          if (LoYorExtra)
  1062.          {  LoY=LoYorExtra;
  1063.             LoYorExtra=0;
  1064.          }
  1065.       }
  1066.       else HiY=c;
  1067.    }
  1068.    else if (tagbits==0x60)     /*LoY or Extra*/
  1069.    {  if (LastTag==0x60)         /*Last was Extra, this is LoY*/
  1070.  
  1071.       {  Extra=LoYorExtra;
  1072.          LoYorExtra=0;
  1073.          LoY=c;
  1074.       }
  1075.       else                       /*Unknown if LoY or Extra*/
  1076.          LoYorExtra=c;
  1077.    }
  1078.    else if (tagbits==0x40)      /*LoX, draw the vector whatever*/
  1079.    {  if (LastTag==0x60 && LoYorExtra)  /* last was LoY */
  1080.         LoY=LoYorExtra;
  1081.       LoX=c;
  1082.       rv=1;
  1083.    }
  1084.    LastTag=tagbits;
  1085.    return(rv);
  1086. }
  1087.  
  1088. /********************************************************************************/
  1089. /* Draw to tekwindow, first checking to make sure we don't go outside boudries  */
  1090. /*  Note: because coordinates are represented with 12-bit unsigned integers,    */
  1091. /*    it is impossible for x to be out of bounds, and y can only be too large   */
  1092. /*    (assuming a y resolution of 3025 rather than 4096)                        */
  1093. /********************************************************************************/
  1094.  
  1095. void Safe_Move(struct RastPort *rp,WORD x,WORD y)
  1096. {
  1097.    lastx=x; lasty=y;
  1098.    if (!(lyok=(y<=maxy))) y=maxy;
  1099.    Move(rp,x,y);
  1100. }
  1101.    
  1102. void Safe_Draw(struct RastPort *rp,WORD x,WORD y)
  1103. {  WORD x0;
  1104.  
  1105.    if (y<=maxy)
  1106.    {  if (lyok) Draw(rp,x,y);     /*All clear*/
  1107.       else
  1108.       {  x0=x + (maxy-y) * (lastx-x) / (lasty-y);
  1109.          Move(rp,x0,maxy);
  1110.          Draw(rp,x,y);
  1111.       }
  1112.    }
  1113.    else
  1114.    {  if (!lyok) Safe_Move(rp,x,y);   /*Won't draw anyway*/
  1115.       else
  1116.       {  x0=lastx + (maxy-lasty) * (x-lastx) / (y-lasty);
  1117.          Draw(rp,x0,maxy);
  1118.       }
  1119.    }
  1120.    lastx=x; lyok=((lasty=y)<=maxy);
  1121. }
  1122.  
  1123. void Safe_Rect(struct RastPort *rp,WORD x,WORD y)
  1124. {  WORD xmin,xmax,ymin,ymax;
  1125.  
  1126.    if (y<=maxy) ymax=y; else ymax=maxy;
  1127.    if (lyok) ymin=lasty; else ymin=maxy;
  1128.    if (ymin>ymax) { xmin=ymin; ymin=ymax; ymax=xmin; }
  1129.    if (lastx>x) { xmax=lastx; xmin=x; }
  1130.    else { xmin=lastx; xmax=x; }
  1131.    RectFill(rp,xmin,ymin,xmax,ymax);
  1132.    lastx=x; lyok=((lasty=y)<=maxy);
  1133. }
  1134.  
  1135. /*****************************************************************************/
  1136. /* Convert screen coords in lastx,lasty  to tek coords in tekx,teky          */
  1137. /*****************************************************************************/
  1138.  
  1139. void scrtotek()
  1140. {
  1141.    tekx=((lastx-tekwindow->BorderLeft)*tekwidth) / winw;
  1142.    teky=((tekwindow->BorderTop+winh-lasty)*tekheight) / winh;
  1143. }
  1144.  
  1145.  
  1146. /********************************************************************************/
  1147. /* Accept IDCMP events from tek window                                          */
  1148. /********************************************************************************/
  1149.  
  1150. void tekpoll(void)
  1151. {
  1152.    struct IntuiMessage *msg;
  1153.  
  1154.    while (tekwindow && (msg=(struct IntuiMessage *)GetMsg(tekwindow->UserPort)))
  1155.    {  switch(msg->Class)
  1156.       {  case RAWKEY : if (bypassmode) ginkeys(msg);
  1157.                        else dokeys(msg);   /* Send to vt100 key handler */
  1158.                        break;
  1159.          case CLOSEWINDOW : ReplyMsg((struct Message *)msg);
  1160.                             closetekwin();
  1161.                             tekmode=0;
  1162.                             break;
  1163.          case NEWSIZE : calctekwinsize();
  1164.                         ReplyMsg((struct Message *)msg);
  1165. /*                        graph_clear();*/
  1166.                         redrawtek();
  1167.                         break;
  1168.          case MENUPICK : tekmenu(msg);
  1169.                          break;
  1170.  
  1171.          case MOUSEMOVE:
  1172.          case MOUSEBUTTONS: if (mode==TEK_GIN) ginmouse(msg);
  1173.                             else ReplyMsg((struct Message *)msg);
  1174.                             break;
  1175.          default: ReplyMsg((struct Message *)msg);
  1176.       }
  1177.    }
  1178. }
  1179.  
  1180. /*****************************************************************************/
  1181. /* Deal with menu events                                                     */
  1182. /*****************************************************************************/
  1183.  
  1184. static int close_it=0;
  1185.  
  1186. void menu_close(void)
  1187. {  close_it=1;
  1188. }
  1189.  
  1190. void tekmenu(struct IntuiMessage *msg)
  1191. {  UWORD Code; /*,menuNum,itemNum,subNum;*/
  1192.    struct MenuItem *item;
  1193.    void (*func)(struct MenuItem *);
  1194.  
  1195.    close_it=0;
  1196.    Code=msg->Code;
  1197.    while ((Code!=MENUNULL) && (!close_it))
  1198.    {   item=ItemAddress(menuStrip,Code);
  1199. /***
  1200.        menuNum=MENUNUM(Code);
  1201.        itemNum=ITEMNUM(Code);
  1202.        subNum=SUBNUM(Code);
  1203. ***/
  1204.        func=(void(*)())GTMENUITEM_USERDATA(item);
  1205.        (*func)(item);
  1206.        Code=item->NextSelect;
  1207.    }
  1208.    ReplyMsg((struct Message *)msg);
  1209.    if (close_it)
  1210.    {  closetekwin();
  1211.       tekmode=0;
  1212.    }
  1213. }
  1214.  
  1215. /*****************************************************************************/
  1216. /* Check state of activatewindow and frontwindow menuitems                   */
  1217. /*****************************************************************************/
  1218.  
  1219. void chk_active(struct MenuItem *item)
  1220. {
  1221.    activateonswitch = item->Flags & CHECKED;
  1222. }
  1223.  
  1224. void chk_front(struct MenuItem *item)
  1225. {
  1226.    forwardonswitch = item->Flags & CHECKED;
  1227. }
  1228.  
  1229.  
  1230.  
  1231. #endif             /*end of ifdef TEKTRONICS*/
  1232.